#include <Poco/JSON/JSON.h>
#include <Poco/JSON/Parser.h>
#include <Poco/Dynamic/Var.h>

// 自定义 make_unique 函数模板，用于单个对象
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

// 自定义 make_unique 函数模板，用于数组
template<typename T>
std::unique_ptr<T> make_unique(std::size_t n) {
    return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
}

// 模拟 JsonPathNode
struct JsonPathNode
{
    Poco::Dynamic::Var value;
    std::string path;
    std::string path2;
};

// 模拟 JsonPathResultAccumulator 委托
using JsonPathResultAccumulator = std::function<void(const Poco::Dynamic::Var&, const std::vector<std::string>&)>;

// 模拟 IJsonPathValueSystem 接口
class IJsonPathValueSystem 
{
public:
    virtual bool HasMember(const Poco::Dynamic::Var& value, const std::string& member) const = 0;
    virtual Poco::Dynamic::Var GetMemberValue(const Poco::Dynamic::Var& value, const std::string& member) const = 0;
    virtual std::vector<std::string> GetMembers(const Poco::Dynamic::Var& value) const = 0;
    virtual bool IsObject(const Poco::Dynamic::Var& value) const = 0;
    virtual bool IsArray(const Poco::Dynamic::Var& value) const = 0;
    virtual bool IsPrimitive(const Poco::Dynamic::Var& value) const = 0;
    virtual ~IJsonPathValueSystem() = default;
};

// 模拟 JsonPathContext
class JsonPathContext 
{
public:
    JsonPathContext(std::unique_ptr<IJsonPathValueSystem> system);

    void SelectTo(const Poco::Dynamic::Var& obj, const std::string& expr, JsonPathResultAccumulator output);

private:
    std::string Normalize(const std::string& expr);

    double evaluateExpression(const std::string& script, const Poco::Dynamic::Var& value);
    bool evaluateLogicalExpression(const std::string& script, const Poco::Dynamic::Var& value);
    bool evaluateFilterExpression(const std::string& script, const Poco::Dynamic::Var& value);

    void Trace(const std::string& expr, const Poco::Dynamic::Var& value, const std::string& path, JsonPathResultAccumulator output);
    void Walk(const std::string& loc, const std::string& expr, const Poco::Dynamic::Var& value, const std::string& path, std::function<void(const std::string&, const std::string&, const std::string&, const Poco::Dynamic::Var&, const std::string&)> callback);

private:
    std::unique_ptr<IJsonPathValueSystem> system;
};

// 实现 IJsonPathValueSystem
class PocoJsonValueSystem : public IJsonPathValueSystem
{
public:
    bool HasMember(const Poco::Dynamic::Var& value, const std::string& member) const override;
    Poco::Dynamic::Var GetMemberValue(const Poco::Dynamic::Var& value, const std::string& member) const override;
    std::vector<std::string> GetMembers(const Poco::Dynamic::Var& value) const override;
    bool IsObject(const Poco::Dynamic::Var& value) const override;
    bool IsArray(const Poco::Dynamic::Var& value) const override;
    bool IsPrimitive(const Poco::Dynamic::Var& value) const override;
};

// 模拟 ListAccumulator
class ListAccumulator 
{
public:
    void Put(const Poco::Dynamic::Var& value, const std::vector<std::string>& indicies);
    const std::vector<JsonPathNode>& GetNodes() const;

private:
    std::vector<JsonPathNode> nodes;
};

ListAccumulator PocoJsonPath(const std::string &jsonStr, const std::string &jsonpath);

ListAccumulator PocoJsonPath(const Poco::Dynamic::Var &jsonVar, const std::string &jsonpath);

void JsonPathSet(Poco::Dynamic::Var &jsonVar,
                 const std::string &jsonpath,
                 const Poco::Dynamic::Var &value);

void JsonPathAdd(Poco::Dynamic::Var &jsonVar,
                 const std::string &jsonpath,
                 const std::string &key,
                 const Poco::Dynamic::Var &value);

void JsonPathDel(Poco::Dynamic::Var &jsonVar,
                 const std::string &jsonpath);
